import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
  Logger,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Inject } from '@nestjs/common';
import { Cache } from 'cache-manager';

/**
 * Scoring模块缓存拦截器
 * 零隐患MFIS规范 - 解决隐患：#6 内存泄漏，#14 信息脱敏
 */
@Injectable()
export class ScoringCacheInterceptor implements NestInterceptor {
  private readonly logger = new Logger(ScoringCacheInterceptor.name);

  constructor(@Inject(CACHE_MANAGER) private readonly cacheManager: Cache) {}

  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    const request = context.switchToHttp().getRequest();
    const response = context.switchToHttp().getResponse();

    // 只缓存GET请求
    if (request.method !== 'GET') {
      return next.handle();
    }

    // 生成缓存键
    const cacheKey = this.generateCacheKey(request);

    // 检查缓存
    return this.handleCache(cacheKey, request, response, next.handle());
  }

  private async handleCache(
    cacheKey: string,
    request: any,
    response: any,
    handler: Observable<any>,
  ): Promise<any> {
    try {
      // 尝试从缓存获取
      const cachedResponse = await this.cacheManager.get(cacheKey);

      if (cachedResponse) {
        this.logger.debug('缓存命中', {
          cache_key: this.sanitizeCacheKey(cacheKey),
          user_id: request.user?.doctor_id,
        });

        // 设置缓存响应头
        response.set('X-Cache', 'HIT');
        response.set('X-Cache-Key', this.sanitizeCacheKey(cacheKey));

        return cachedResponse;
      }

      // 缓存未命中，执行请求
      return new Promise((resolve, reject) => {
        handler.subscribe({
          next: (data) => {
            // 缓存响应（异步，不阻塞响应）
            this.cacheResponse(cacheKey, data, request).catch(error => {
              this.logger.warn('缓存响应失败', {
                cache_key: this.sanitizeCacheKey(cacheKey),
                error: error.message,
              });
            });

            // 设置缓存响应头
            response.set('X-Cache', 'MISS');
            response.set('X-Cache-Key', this.sanitizeCacheKey(cacheKey));

            resolve(data);
          },
          error: (error) => {
            reject(error);
          },
        });
      });

    } catch (error) {
      this.logger.warn('缓存处理失败', {
        cache_key: this.sanitizeCacheKey(cacheKey),
        error: error.message,
      });

      // 缓存失败不应该影响正常请求
      return handler;
    }
  }

  private generateCacheKey(request: any): string {
    const user = request.user;
    const userId = user?.doctor_id || 'anonymous';
    const url = request.url;
    const query = JSON.stringify(request.query || {});

    // 生成安全的缓存键
    const keyData = `scoring:${userId}:${url}:${Buffer.from(query).toString('base64')}`;
    return keyData.replace(/[^a-zA-Z0-9:]/g, '_').substring(0, 200);
  }

  private async cacheResponse(cacheKey: string, data: any, request: any): Promise<void> {
    try {
      // 根据响应类型设置不同的TTL
      let ttl = 60; // 默认1分钟

      if (request.url.includes('/status/')) {
        ttl = 30; // 状态查询30秒
      } else if (request.url.includes('/result/')) {
        ttl = 300; // 结果查询5分钟
      } else if (request.url.includes('/list')) {
        ttl = 60; // 列表查询1分钟
      }

      await this.cacheManager.set(cacheKey, data, ttl);

      this.logger.debug('响应已缓存', {
        cache_key: this.sanitizeCacheKey(cacheKey),
        ttl,
        user_id: request.user?.doctor_id,
      });

    } catch (error) {
      this.logger.error('缓存写入失败', {
        cache_key: this.sanitizeCacheKey(cacheKey),
        error: error.message,
      });
    }
  }

  private sanitizeCacheKey(cacheKey: string): string {
    // 脱敏缓存键，避免泄露用户ID等信息
    return cacheKey
      .replace(/scoring:\d+:/g, 'scoring:[USER_ID]:')
      .substring(0, 50);
  }
}